package vcp.entity.utility;

import java.io.Serializable;
import java.util.ListIterator;

import org.joda.time.Minutes;

import vcp.entity.Car;
import vcp.entity.Lot;
import vcp.entity.Site;
import vcp.entity.Subscription;
import vcp.enums.LotStatus;
import vcp.enums.SiteEnum;
import vcp.server.DAO.CarDAO;
import vcp.server.DAO.LotDAO;
import vcp.server.DAO.SiteDAO;
import vcp.server.DAO.SubscriptionDAO;
/**
 * 
 * @author VCP team
 *<p> robot class </p>
 */
public class Robot implements Serializable
{

	/**
	 * 
	 */
	private static final long serialVersionUID = - 8227434655572721229L;

	private final SiteEnum siteEnum;
	private final SiteDAO siteDAO;
	/**
	 * constructor
	 * @param site
	 */
	protected Robot ( SiteEnum site )
	{
		this.siteDAO = new SiteDAO();
		this.siteEnum = site;
	}
	/**
	 * getter
	 * @param newSubscription
	 * @return available lot
	 */
	public synchronized Lot getAvailableLot ( Subscription newSubscription )
	{
		Site site = this.siteDAO.findByID(this.siteEnum.getSiteID());
		this.siteDAO.getSiteLotsOnDemand(site);
		SubscriptionDAO subscriptionDAO = new SubscriptionDAO();
		Lot lot = null;
		ListIterator <Lot> lotMap = site.getParkingMatrix().listIterator();
		while ( lotMap.hasNext() )
		{
			Lot temp = lotMap.next();
			if ( temp.getLotStatus() != LotStatus.NON_WORKING )
			{
				if ( temp.getLotStatus() == LotStatus.FREE )
				{
					lot = temp;
					break;
				}
				else
				{
					CarDAO carDAO = new CarDAO();
					Car car = carDAO.findByID(temp.getCarID());
					Subscription subscription = subscriptionDAO.findByID(car.getSubscriptionID());
					if ( Minutes.minutesBetween(newSubscription.getEstimatedLeaveDate(), subscription.getEstimatedLeaveDate()).getMinutes() > 0 )
					{
						lot = this.swap(lotMap, temp);
						break;
					}
				}

			}
		}

		return lot;
	}
	/**
	 * swap between lots
	 * @param lotMap
	 * @param temp
	 * @return lot
	 */
	private Lot swap ( ListIterator <Lot> lotMap, Lot temp )
	{

		LotDAO lotDAO = new LotDAO();
		Lot prevLot = temp;

		while ( lotMap.hasNext() )
		{
			Lot curretLot = lotMap.next();
			Lot swap = null;
			if ( curretLot.getLotStatus() != LotStatus.NON_WORKING )
			{
				if ( curretLot.getLotStatus() == LotStatus.FREE )
				{
					lotDAO.updateCarInLot(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getCarID());
					lotDAO.updateLotStatusByID(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getLotStatus());
					lotDAO.updateReservedBySubscription(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getReservedBySubscription());
					break;
				}
				else
				{
					swap = curretLot;
					lotDAO.updateCarInLot(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getCarID());
					lotDAO.updateLotStatusByID(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getLotStatus());
					lotDAO.updateReservedBySubscription(curretLot.getSiteID(), curretLot.getFloor(), curretLot.getRow(), curretLot.getColumn(), prevLot.getReservedBySubscription());
					prevLot = swap;
				}
			}

		}
		temp.setCarID(null);
		temp.setLotStatus(LotStatus.FREE);
		temp.setReservedBySubscription(null);
		lotDAO.updateCarInLot(temp.getSiteID(), temp.getFloor(), temp.getRow(), temp.getColumn(), temp.getCarID());
		lotDAO.updateLotStatusByID(temp.getSiteID(), temp.getFloor(), temp.getRow(), temp.getColumn(), temp.getLotStatus());
		lotDAO.updateReservedBySubscription(temp.getSiteID(), temp.getFloor(), temp.getRow(), temp.getColumn(), temp.getReservedBySubscription());
		return temp;
	}
	/**
	 *  removes car from lot
	 */
	public synchronized void removeCar ()
	{
		Site site = this.siteDAO.findByID(this.siteEnum.getSiteID());
		this.siteDAO.getSiteLotsOnDemand(site);
		ListIterator <Lot> lotMap = site.getParkingMatrix().listIterator();
		LotDAO lotDAO = new LotDAO();
		Lot currentLot=null;
		while(lotMap.hasNext())
		{
			currentLot = lotMap.next();
			if(currentLot.getLotStatus() == LotStatus.FREE)
			{
				break;
			}
		}

		while ( lotMap.hasNext() )
		{
			Lot nextLot = lotMap.next();
			if(nextLot.getLotStatus() != LotStatus.NON_WORKING)
			{
				if (nextLot.getLotStatus() != LotStatus.FREE )
				{
					lotDAO.updateCarInLot(currentLot.getSiteID(), currentLot.getFloor(), currentLot.getRow(), currentLot.getColumn(), nextLot.getCarID());
					lotDAO.updateLotStatusByID(currentLot.getSiteID(), currentLot.getFloor(), currentLot.getRow(), currentLot.getColumn(), nextLot.getLotStatus());
					lotDAO.updateReservedBySubscription(currentLot.getSiteID(), currentLot.getFloor(), currentLot.getRow(), currentLot.getColumn(), nextLot.getReservedBySubscription());
					lotDAO.updateCarInLot(nextLot.getSiteID(), nextLot.getFloor(), nextLot.getRow(), nextLot.getColumn(), null);
					lotDAO.updateLotStatusByID(nextLot.getSiteID(), nextLot.getFloor(), nextLot.getRow(), nextLot.getColumn(), LotStatus.FREE);
					lotDAO.updateReservedBySubscription(nextLot.getSiteID(), nextLot.getFloor(), nextLot.getRow(), nextLot.getColumn(), null);
					currentLot = nextLot;
				}
			}
		}

	}



}
